package cn.chiship.framework.business.biz.member.service.impl;

import cn.chiship.framework.business.biz.base.service.impl.BusinessAsyncService;
import cn.chiship.framework.business.biz.cashier.pojo.dto.WithdrawalApplicationDto;
import cn.chiship.framework.business.biz.member.enmus.MemberWalletChangeModuleEnum;
import cn.chiship.framework.business.biz.member.enmus.WithdrawalApplicationStatusEnum;
import cn.chiship.framework.business.biz.member.entity.MemberUser;
import cn.chiship.framework.business.biz.member.mapper.MemberUserMapper;
import cn.chiship.framework.business.biz.member.mapper.MemberUserWalletChangeMapper;
import cn.chiship.framework.business.biz.member.pojo.dto.MemberUserWithdrawalExamineDto;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.util.DateUtils;
import cn.chiship.sdk.core.util.PrintUtil;
import cn.chiship.sdk.core.util.RandomUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.framework.base.BaseServiceImpl;
import cn.chiship.framework.business.biz.member.mapper.MemberUserWithdrawalApplicationMapper;
import cn.chiship.framework.business.biz.member.entity.MemberUserWithdrawalApplication;
import cn.chiship.framework.business.biz.member.entity.MemberUserWithdrawalApplicationExample;
import cn.chiship.framework.business.biz.member.service.MemberUserWithdrawalApplicationService;
import cn.chiship.sdk.framework.pojo.dto.export.ExportDto;
import cn.chiship.sdk.framework.pojo.dto.export.ExportTransferDataDto;
import cn.chiship.sdk.pay.core.enums.PayEnum;
import cn.chiship.sdk.pay.core.model.PayTransferModel;
import cn.chiship.sdk.pay.factory.PayFactory;
import cn.chiship.sdk.pay.services.PaymentService;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 提现申请业务接口实现层
 * 2024/12/17
 *
 * @author lijian
 */
@Service
public class MemberUserWithdrawalApplicationServiceImpl extends BaseServiceImpl<MemberUserWithdrawalApplication, MemberUserWithdrawalApplicationExample> implements MemberUserWithdrawalApplicationService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MemberUserWithdrawalApplicationServiceImpl.class);

    @Resource
    MemberUserWithdrawalApplicationMapper memberUserWithdrawalApplicationMapper;
    @Resource
    MemberUserMapper memberUserMapper;
    @Resource
    BusinessAsyncService businessAsyncService;
    @Resource
    MemberUserWalletChangeMapper memberUserWalletChangeMapper;

    @Value("${chiship.pay.domain.notify}")
    private String notifyDomain;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult withdrawalApplication(WithdrawalApplicationDto withdrawalApplicationDto, CacheUserVO cacheUserVO) {
        MemberUserWithdrawalApplication memberUserWithdrawalApplication = new MemberUserWithdrawalApplication();
        BeanUtils.copyProperties(withdrawalApplicationDto, memberUserWithdrawalApplication);
        memberUserWithdrawalApplication.setUserId(cacheUserVO.getId());
        memberUserWithdrawalApplication.setUserPhone(cacheUserVO.getMobile());

        if (memberUserWithdrawalApplication.getMoney().compareTo(BigDecimal.valueOf(0.1)) < 0) {
            return BaseResult.error("提现最低金额为0.1元，无法提现");
        }
        MemberUser memberUser = memberUserMapper.selectByPrimaryKey(memberUserWithdrawalApplication.getUserId());
        if (StringUtil.isNull(memberUser)) {
            return BaseResult.error("用户不存在");
        }

        if (memberUser.getWallet().compareTo(BigDecimal.ZERO) <= 0) {
            return BaseResult.error("钱包余额为0，无法提现");
        }
        if (memberUser.getWallet().compareTo(memberUserWithdrawalApplication.getMoney()) < 0) {
            return BaseResult.error("钱包余额不足" + memberUserWithdrawalApplication.getMoney() + "，无法提现");
        }
        memberUserWithdrawalApplication.setNo("T" + DateUtils.dateTimeNow() + RandomUtil.getString(5));
        memberUserWithdrawalApplication.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_IN_REVIEW.getStatus());
        memberUserWithdrawalApplication.setReason(memberUserWithdrawalApplication.getReason());
        super.insertSelective(memberUserWithdrawalApplication);

        businessAsyncService.changeMemberWallet(
                memberUserWithdrawalApplication.getUserId(),
                memberUserWithdrawalApplication.getMoney(),
                true,
                "申请提现",
                MemberWalletChangeModuleEnum.MEMBER_WALLET_CHANGE_MODULE_WITHDRAWAL,
                memberUserWithdrawalApplication.getId());

        return BaseResult.ok();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult examine(MemberUserWithdrawalExamineDto memberUserWithdrawalExamineDto, CacheUserVO cacheUserVO) {
        MemberUserWithdrawalApplication memberUserWithdrawalApplication = memberUserWithdrawalApplicationMapper.selectByPrimaryKey(memberUserWithdrawalExamineDto.getId());
        if (StringUtil.isNull(memberUserWithdrawalApplication)) {
            return BaseResult.error("无效的提现申请");
        }
        Byte status = memberUserWithdrawalExamineDto.getStatus();
        //1 通过 2：拒绝
        if (WithdrawalApplicationStatusEnum.WITHDRAWAL_APPROVED_REJECTED.getStatus().equals(status)) {
            /**
             * 拒绝后原路退回金额
             */

            businessAsyncService.changeMemberWallet(
                    memberUserWithdrawalApplication.getUserId(),
                    memberUserWithdrawalApplication.getMoney(),
                    false,
                    "申请提现拒绝，原路退还金额",
                    MemberWalletChangeModuleEnum.MEMBER_WALLET_CHANGE_MODULE_WITHDRAWAL,
                    memberUserWithdrawalApplication.getId()
            );

        } else if (WithdrawalApplicationStatusEnum.WITHDRAWAL_APPROVED.getStatus().equals(status)) {
            PayEnum payEnum = PayEnum.getPayEnum(memberUserWithdrawalApplication.getChannelWay());

            if (payEnum.getType().equals(PayEnum.PAY_ZFB.getType())) {
                return BaseResult.error("还未接入[" + payEnum.getMessage() + "]渠道的提现方式");
            }
            status = WithdrawalApplicationStatusEnum.WITHDRAWAL_PAYING.getStatus();
            PaymentService paymentService = PayFactory.getPaymentService(payEnum);
            PayTransferModel payTransferModel = new PayTransferModel(
                    memberUserWithdrawalApplication.getNo(),
                    memberUserWithdrawalApplication.getOpenId(),
                    memberUserWithdrawalApplication.getMoney().doubleValue(),
                    memberUserWithdrawalApplication.getReason(),
                    memberUserWithdrawalApplication.getReason(),
                    notifyDomain
            );
            BaseResult baseResult = paymentService.doTransfer(payTransferModel);
            if (!baseResult.isSuccess()) {
                return baseResult;
            }
            PrintUtil.console(baseResult);
            JSONObject resultJson = (JSONObject) baseResult.getData();
            String batchStatus = resultJson.getString("batch_status");
            if (Arrays.asList("ACCEPTED", "PROCESSING").contains(batchStatus)) {
                memberUserWithdrawalApplication.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_PAYING.getStatus());
            }
            if (Arrays.asList("FINISHED").contains(batchStatus)) {
                memberUserWithdrawalApplication.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_SUCCESS.getStatus());
            }
            if (Arrays.asList("CLOSED").contains(batchStatus)) {
                memberUserWithdrawalApplication.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_FAIL.getStatus());

                /**
                 * 拒绝后原路退回金额
                 */
                businessAsyncService.changeMemberWallet(
                        memberUserWithdrawalApplication.getUserId(),
                        memberUserWithdrawalApplication.getMoney(),
                        false,
                        "申请提现拒绝，原路退还金额",
                        MemberWalletChangeModuleEnum.MEMBER_WALLET_CHANGE_MODULE_WITHDRAWAL,
                        memberUserWithdrawalApplication.getId()
                );
            }
        }
        memberUserWithdrawalApplication.setApproverId(cacheUserVO.getId());
        memberUserWithdrawalApplication.setApproverName(cacheUserVO.getRealName());
        memberUserWithdrawalApplication.setStatus(status);
        memberUserWithdrawalApplication.setStatusDesc(memberUserWithdrawalExamineDto.getStatusDesc());
        super.updateByPrimaryKeySelective(memberUserWithdrawalApplication);

        return BaseResult.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult reconciliation(String no) {
        PrintUtil.console("转账单号：" + no);
        MemberUserWithdrawalApplicationExample memberUserWithdrawalApplicationExample = new MemberUserWithdrawalApplicationExample();
        memberUserWithdrawalApplicationExample.createCriteria().andNoEqualTo(no);
        List<MemberUserWithdrawalApplication> applications = memberUserWithdrawalApplicationMapper.selectByExample(memberUserWithdrawalApplicationExample);
        if (applications.isEmpty()) {
            return BaseResult.error("无效的申请");
        }
        MemberUserWithdrawalApplication application = applications.get(0);
        PayEnum payEnum = PayEnum.getPayEnum(application.getChannelWay());

        PaymentService paymentService = PayFactory.getPaymentService(payEnum);
        if (payEnum.getType().equals(PayEnum.PAY_ZFB.getType())) {
            return BaseResult.error("还未接入[" + payEnum.getMessage() + "]渠道的提现对账");
        }
        BaseResult baseResult = paymentService.doTransferQuery(no);
        if (!baseResult.isSuccess()) {
            application.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_FAIL.getStatus());
            application.setStatusDesc(baseResult.getData().toString());

            /**
             * 拒绝后原路退回金额
             */
            businessAsyncService.changeMemberWallet(
                    application.getUserId(),
                    application.getMoney(),
                    false,
                    "提现打款失败，原路退还金额",
                    MemberWalletChangeModuleEnum.MEMBER_WALLET_CHANGE_MODULE_WITHDRAWAL,
                    application.getId()
            );

            return BaseResult.ok();
        }
        /**
         * {
         *     "code": 200,
         *     "data": {
         *         "update_time": "2024-07-01T14:42:56+08:00",
         *         "mchid": "1632362985",
         *         "batch_id": "131000606011801535063152024070157548170797",
         *         "transfer_amount": 10,
         *         "openid": "oE9-k6_QktAAsLRZOVCrTyCyhZCI",
         *         "appid": "wx1da1b00d334a5599",
         *         "detail_status": "FAIL",
         *         "out_batch_no": "967644733825597440",
         *         "out_detail_no": "967644733825597440",
         *         "detail_id": "132000606011801535063152024070179416756624",
         *         "fail_reason": "MERCHANT_REJECT",
         *         "transfer_remark": "测试转账"
         *     },
         *     "message": "操作成功",
         *     "success": true
         * }
         */
        JSONObject resultJson = (JSONObject) baseResult.getData();

        /**
         * WAIT_PAY: 待确认。待商户确认, 符合免密条件时, 系统会自动扭转为转账中
         * PROCESSING:转账中。正在处理中，转账结果尚未明确
         * SUCCESS:转账成功
         * FAIL:转账失败。需要确认失败原因后，再决定是否重新发起对该笔明细单的转账（并非整个转账批次单）
         */
        String mchId = resultJson.getString("mchid");
        String batchId = resultJson.getString("batch_id");

        String status = resultJson.getString("detail_status");
        String reason = resultJson.getString("fail_reason");
        Map<String, String> reasonMap = new HashMap<>(7);
        reasonMap.put("ACCOUNT_FROZEN", "该用户账户被冻结");
        reasonMap.put("REAL_NAME_CHECK_FAIL", "收款人未实名认证，需要用户完成微信实名认证");
        reasonMap.put("NAME_NOT_CORRECT", "收款人姓名校验不通过，请核实信息");
        reasonMap.put("OPENID_INVALID", "Openid格式错误或者不属于商家公众账号");
        reasonMap.put("TRANSFER_QUOTA_EXCEED", "超过用户单笔收款额度，核实产品设置是否准确");
        reasonMap.put("DAY_RECEIVED_QUOTA_EXCEED", " 超过用户单日收款额度，核实产品设置是否准确");
        reasonMap.put("MONTH_RECEIVED_QUOTA_EXCEED", "超过用户单月收款额度，核实产品设置是否准确");
        reasonMap.put("DAY_RECEIVED_COUNT_EXCEED", "超过用户单日收款次数，核实产品设置是否准确");
        reasonMap.put("PRODUCT_AUTH_CHECK_FAIL", "未开通该权限或权限被冻结，请核实产品权限状态");
        reasonMap.put("OVERDUE_CLOSE", "超过系统重试期，系统自动关闭");
        reasonMap.put("ID_CARD_NOT_CORRECT", "收款人身份证校验不通过，请核实信息");
        reasonMap.put("ACCOUNT_NOT_EXIST", "该用户账户不存在");
        reasonMap.put("TRANSFER_RISK", "该笔转账可能存在风险，已被微信拦截");
        reasonMap.put("OTHER_FAIL_REASON_TYPE", "其它失败原因");
        reasonMap.put("REALNAME_ACCOUNT_RECEIVED_QUOTA_EXCEED", "用户账户收款受限，请引导用户在微信支付查看详情");
        reasonMap.put("RECEIVE_ACCOUNT_NOT_PERMMIT", "未配置该用户为转账收款人，请在产品设置中调整，添加该用户为收款人");
        reasonMap.put("PAYEE_ACCOUNT_ABNORMAL", "用户账户收款异常，请联系用户完善其在微信支付的身份信息以继续收款");
        reasonMap.put("PAYER_ACCOUNT_ABNORMAL", "商户账户付款受限，可前往商户平台获取解除功能限制指引");
        reasonMap.put("TRANSFER_SCENE_UNAVAILABLE", "该转账场景暂不可用，请确认转账场景ID是否正确");
        reasonMap.put("TRANSFER_SCENE_INVALID", "你尚未获取该转账场景，请确认转账场景ID是否正确");
        reasonMap.put("TRANSFER_REMARK_SET_FAIL", "转账备注设置失败， 请调整后重新再试");
        reasonMap.put("RECEIVE_ACCOUNT_NOT_CONFIGURE", "请前往商户平台-商家转账到零钱-前往功能-转账场景中添加");
        reasonMap.put("BLOCK_B2C_USERLIMITAMOUNT_BSRULE_MONTH", "超出用户单月转账收款20w限额，本月不支持继续向该用户付款");
        reasonMap.put("BLOCK_B2C_USERLIMITAMOUNT_MONTH", "用户账户存在风险收款受限，本月不支持继续向该用户付款");
        reasonMap.put("MERCHANT_REJECT", "商户员工（转账验密人）已驳回转账");
        reasonMap.put("MERCHANT_NOT_CONFIRM", "商户员工（转账验密人）超时未验密");

        application.setBatchId(batchId);
        application.setMchId(mchId);


        if (Arrays.asList("WAIT_PAY", "PROCESSING").contains(status)) {
            application.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_PAYING.getStatus());
        }
        if (Arrays.asList("SUCCESS").contains(status)) {
            application.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_SUCCESS.getStatus());
        }
        if (Arrays.asList("FAIL").contains(status)) {
            application.setStatus(WithdrawalApplicationStatusEnum.WITHDRAWAL_FAIL.getStatus());
            if (reasonMap.containsKey(reason)) {
                application.setStatusDesc(reasonMap.get(reason));
            } else {
                application.setStatusDesc(reason);
            }
            /**
             * 拒绝后原路退回金额
             */
            businessAsyncService.changeMemberWallet(
                    application.getUserId(),
                    application.getMoney(),
                    false,
                    "提现打款失败，原路退还金额",
                    MemberWalletChangeModuleEnum.MEMBER_WALLET_CHANGE_MODULE_WITHDRAWAL,
                    application.getId()
            );

        }
        application.setNotifyTime(System.currentTimeMillis());
        memberUserWithdrawalApplicationMapper.updateByPrimaryKeySelective(application);
        return BaseResult.ok();

    }

    @Override
    public ExportTransferDataDto assemblyExportData(ExportDto exportDto) {
        Map<String, Object> paramMap = exportDto.getParamMap();
        Byte status = null;
        if (paramMap.containsKey("status")) {
            status = Byte.valueOf(paramMap.get("status").toString());
        }

        MemberUserWithdrawalApplicationExample memberUserWithdrawalApplicationExample = new MemberUserWithdrawalApplicationExample();
        if (!StringUtil.isNull(status)) {
            if (!Byte.valueOf("-1").equals(status)) {
                memberUserWithdrawalApplicationExample.createCriteria().andStatusEqualTo(status);
            }
        }
        memberUserWithdrawalApplicationExample.setOrderByClause("gmt_created desc");
        List<MemberUserWithdrawalApplication> memberUserWithdrawalApplications = memberUserWithdrawalApplicationMapper.selectByExample(memberUserWithdrawalApplicationExample);

        String fileName = "提现数据清单";
        String sheetName = "提现数据清单";
        String sheetTitle = "提现数据清单";
        List<String> labels = new ArrayList<>();
        List<List<String>> valueList = new ArrayList<>();
        labels.add("申请时间");
        labels.add("提现单号");
        labels.add("提现金额");
        labels.add("提现人员");
        labels.add("提现状态");
        labels.add("提现渠道");
        labels.add("提现原因");
        labels.add("审批人");
        for (MemberUserWithdrawalApplication withdrawalApplication : memberUserWithdrawalApplications) {
            List<String> values = new ArrayList<>();
            values.add(DateUtils.dateTime(withdrawalApplication.getGmtCreated()));
            values.add(withdrawalApplication.getNo());
            values.add(withdrawalApplication.getMoney() + "");
            values.add(withdrawalApplication.getUserPhone());
            String statusDesc = WithdrawalApplicationStatusEnum.getWithdrawalApplicationStatusEnum(withdrawalApplication.getStatus()).getMessage();
            if (!StringUtil.isNullOrEmpty(withdrawalApplication.getStatusDesc())) {
                statusDesc += "【" + withdrawalApplication.getStatusDesc() + "】";
            }
            values.add(statusDesc);
            values.add(withdrawalApplication.getChannelWay());
            values.add(withdrawalApplication.getReason());
            values.add(withdrawalApplication.getApproverName());
            valueList.add(values);
        }

        return new ExportTransferDataDto(fileName, sheetName, sheetTitle, labels, valueList, valueList.size());
    }

}
